package cc.sheji.Service;


import cc.sheji.config.StaticConfig;
import cc.sheji.domain.Order;
import cc.sheji.domain.OrderQueryCriteria;
import cc.sheji.domain.PayLog;
import cc.sheji.reposity.OrderRepository;
import cc.sheji.util.QueryHelp;
import cn.dev33.satoken.stp.StpUtil;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.BiConsumer;


@Service
public class OrderService {

    @Autowired
    OrderRepository orderRepository;
    @Autowired
    PayLogService payLogService;
    @Autowired
    UserService userService;
    @Autowired
    StaticConfig staticConfig;

    @Value("${wechatPayCallHandle}")
    String wechatPayCallHandle;

    NativePayService service;
    JsapiServiceExtension service1;

    @PostConstruct
    public void init() {
        service1 = new JsapiServiceExtension.Builder().config(staticConfig.getConfig()).build();

        service = new NativePayService.Builder().config(staticConfig.getConfig()).build();
    }


    public  HashMap<String ,String > create1(Order order) {

// 跟之前下单示例一样，填充预下单参数
        com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
        com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
        amount.setTotal(order.getMoney());
        request.setAmount(amount);
        request.setAppid("wx85dd784a1d6ddc9d");
        request.setMchid("1612407211");
        request.setDescription(order.getName());
        request.setNotifyUrl(wechatPayCallHandle);
        request.setOutTradeNo("out_trade_no" + order.getId());
        com.wechat.pay.java.service.payments.jsapi.model.Payer payer = new Payer();
        payer.setOpenid(order.getOpenId());
        request.setPayer(payer);
       // response包含了调起支付所需的所有参数，可直接用于前端调起支付
        PrepayWithRequestPaymentResponse response = service1.prepayWithRequestPayment(request);

        HashMap<String ,String > hashMap=new HashMap<>();

        hashMap.put("appId",response.getAppId());
        hashMap.put("nonceStr",response.getNonceStr());
        hashMap.put("packageVal",response.getPackageVal());
        hashMap.put("signType",response.getSignType());
        hashMap.put("timeStamp",response.getTimeStamp());
        hashMap.put("paySign",response.getPaySign());
        return hashMap;
    }


    public String createPayInfo(Order order) {

        // 构建service
        // request.setXxx(val)设置所需参数，具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(order.getMoney());
        request.setAmount(amount);
        request.setAppid("wx85dd784a1d6ddc9d");
        request.setMchid("1612407211");
        request.setDescription(order.getName());
        request.setNotifyUrl(wechatPayCallHandle);
        request.setOutTradeNo("out_trade_no" + order.getId());


        //   调用下单方法，得到应答
        PrepayResponse response = service.prepay(request);
        return response.getCodeUrl();
    }


    public Order create(Order entity) {
        System.out.println("openid:"+entity.getOpenId());
        entity.setUserId(StpUtil.getLoginIdAsLong());
        entity.setId(null);
        entity.setName("设辑支付");
        switch (entity.getType()) {
            case 1:
                entity.setCoin(toCoin(entity.getMoney() / 100d));
                break;
            case 2:
                break;
        }
        entity.setState(0);
        entity = orderRepository.save(entity);
        String openId = entity.getOpenId();
        if(openId!=null&&openId.length()>0){
            HashMap<String, String> stringStringHashMap = create1(entity);
            entity.setPayMap(stringStringHashMap);

        }else {
            String payInfo = createPayInfo(entity);
            entity.setPayUrl(payInfo);
        }

        entity = orderRepository.save(entity);
        return entity;
    }


    public int toCoin(Double num) {
        double temp = 0;
        if (num < 20) {
            temp = num / 0.1;
        } else if (num < 100) {
            temp = num / 0.095;
        } else if (num < 300) {
            temp = num / 0.09;
        } else {
            temp = num / 0.085;
        }
        temp = Math.ceil(temp);
        return (int) temp;
    }


    public Order get(Long id) {

        Order entity = orderRepository.findById(id).get();
        return entity;
    }

    public Order update(Order entity) {

        entity = orderRepository.save(entity);
        return entity;
    }

    public Order updatePayStateFinish(Long id) {

        Order order = orderRepository.findById(id).get();
        order.setState(1);
        order = orderRepository.save(order);
        PayLog payLog = new PayLog();
        switch (order.getType()) {
            case 1:

                payLog.setUserId(order.getUserId());
                payLog.setContent("用户充值了");
                payLog.setMoney(order.getMoney());
                payLogService.create(payLog);
                userService.addCoin(order.getUserId(), order.getCoin());
                break;
            case 2:
                payLog.setUserId(order.getUserId());
                payLog.setContent("用户开通会员");
                payLog.setMoney(order.getMoney());
                payLogService.create(payLog);
                userService.updateVip(order.getUserId(), 1);
                break;
            case 3:
                payLog.setUserId(order.getUserId());
                payLog.setContent("用户开通会员");
                payLog.setMoney(order.getMoney());
                payLogService.create(payLog);
                userService.updateVip(order.getUserId(), 2);
                break;
            case 4:
                payLog.setUserId(order.getUserId());
                payLog.setContent("用户开通会员");
                payLog.setMoney(order.getMoney());
                payLogService.create(payLog);
                userService.updateVip(order.getUserId(), 3);
                break;
            case 5:
                payLog.setUserId(order.getUserId());
                payLog.setContent("用户开通会员");
                payLog.setMoney(order.getMoney());
                payLogService.create(payLog);
                userService.updateVip(order.getUserId(), 4);
                break;
        }
        return order;
    }


    public List<Order> list(OrderQueryCriteria criteria, Pageable pageable) {
        Page<Order> page = orderRepository.findAll((root, criteriaQuery, criteriaBuilder) ->
                QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return page.getContent();

    }

    public Object getAll(OrderQueryCriteria criteria) {

        criteria.setUserId(StpUtil.getLoginIdAsLong());
        criteria.setState(1);

        DateFormat format = new SimpleDateFormat("yyyy-MM");
        List<Order> all = orderRepository.findAll((root, criteriaQuery, criteriaBuilder) ->
                QueryHelp.getPredicate(root, criteria, criteriaBuilder));
        LinkedHashMap<String, List<Order>> map = new LinkedHashMap<>();
        for (int i = 0; i < all.size(); i++) {
            Order payLog = all.get(i);
            String date = format.format(payLog.getCreateTime());
            List<Order> list = map.get(date);
            if (list == null) {
                list = new ArrayList<>();
                map.put(date, list);
            }
            list.add(payLog);
        }
        List returnData = new ArrayList();
        map.forEach(new BiConsumer<String, List<Order>>() {
            @Override
            public void accept(String s, List<Order> payLogs) {
                Map item = new HashMap();
                item.put("key", s);
                item.put("value", payLogs);
                returnData.add(item);
            }
        });
        return returnData;
    }

    public long total() {
        try{
            return orderRepository.sumPrice();
        }catch ( Exception e){
            return 0;
        }
    }
}
